#include "StateManager.h"
#include "RenderManager.h"
#include "Resources.h"
#include "Define.h"
#include "GameTime.h"

StateManager::StateManager(std::shared_ptr<InputManager> inputManager)
{
	_inputManager = inputManager;
	Resources::getSingletonPtr()->loadSprite(_blank, "BLACK_FADE");
	_blank.setScale(VSW_05, VSH_05);
	_blank.setPosition(0.0f, 0.0f);
	_direction = 0.0f;
	_alphaTransition = 0;
	_alpha = sf::Color::White;
	_transition = false;
	_loadQueuedStates = false;
}

StateManager::~StateManager(void)
{
}

void StateManager::update()
{
	if (!_removeList.empty())
	{
		for (auto it = _removeList.begin(); it != _removeList.end(); it++)
		{
			(*it)->shutdown();
			(*it)->unloadContent();
			_states.remove(*it);
			delete *it;
			*it = nullptr;
		}
		_removeList.clear();
	}

	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getUpdateState())
			(*it)->update();
	}

	if (_transition)
	{
		_alphaTransition = _direction * GameTime::getSingleton()->deltaTime();
		if (_direction > 0)
			_virtualAlpha = std::min<float>(255.0f, _virtualAlpha + _alphaTransition);
		else if (_direction < 0)
			_virtualAlpha = std::max<float>(0.0f, _virtualAlpha + _alphaTransition);
	}
}

void StateManager::draw(RenderManager* renderManager)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getDrawState())
			(*it)->draw(renderManager);
	}

	if (_transition)
	{
		_alpha.a = static_cast<sf::Uint8>(_virtualAlpha);
		_blank.setColor(_alpha);
		renderManager->setView(VIEW_FRONT);
		renderManager->draw(_blank);
		if ((_alpha.a == 0 && _direction < 0) || (_alpha.a == 255 && _direction > 0))
		{
			_transition = false;
			if (_loadQueuedStates)
				loadQueuedStates();
		}
	}
}

void StateManager::addState(State* state, bool active)
{
	state->setInputManager(_inputManager);
	state->setStateManager(this);
	state->loadContent();
	state->setActiveState(active);
	_states.push_back(state);
}

void StateManager::queueState(State* state, bool active)
{
	state->setInputManager(_inputManager);
	state->setStateManager(this);
	state->setActiveState(active);
	_queue.push_back(state);
}

void StateManager::stateTransition(float direction, bool loadQueuedStates)
{
	if (direction > 0)
		_alpha.a = 0;
	else if (direction < 0)
		_alpha.a = 255;
	_virtualAlpha = static_cast<float>(_alpha.a);
	_direction = direction;
	_loadQueuedStates = loadQueuedStates;
	_transition = true;
}

void StateManager::loadQueuedStates()
{
	_loadQueuedStates = false;
	for (auto it = _states.begin(); it != _states.end(); it++)
		_removeList.push_back(*it);

	for (auto it = _queue.begin(); it != _queue.end(); it++)
	{
		_states.push_back(*it);
		(*it)->loadContent();
		if ((*it)->isActive())
			(*it)->initialize();
	}
	_queue.clear();
}

///////////////////////////////
/// Update & Draw Management
void StateManager::setInputUpdate(bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
		(*it)->setInputUpdate(value);
}

void StateManager::setInputUpdate(const std::string& id, bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getID() == id)
		{
			(*it)->setInputUpdate(value);
			break;
		}
	}
}

void StateManager::setUpdateState(bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
		(*it)->setUpdateState(value);
}

void StateManager::setUpdateState(const std::string& id, bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getID() == id)
		{
			(*it)->setUpdateState(value);
			break;
		}
	}
}

void StateManager::setDrawState(bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
		(*it)->setDrawState(value);
}

void StateManager::setDrawState(const std::string& id, bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getID() == id)
		{
			(*it)->setDrawState(value);
			break;
		}
	}
}

void StateManager::setActiveState(bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
		(*it)->setActiveState(value);
}

void StateManager::setActiveState(const std::string& id, bool value)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getID() == id)
		{
			(*it)->setActiveState(value);
			break;
		}
	}
}

void StateManager::removeState(State* state)
{
	state->shutdown();
	state->unloadContent();
	_states.remove(state);
	delete state;
	state = nullptr;
}

void StateManager::skipUpdateCycle(const std::string& id, short cycles)
{
	for (auto it = _states.begin(); it != _states.end(); it++)
	{
		if ((*it)->getID() == id)
		{
			(*it)->setSkipUpdateCycles(cycles);
			break;
		}
	}
}